#ifndef __SMART_ARRAY_H__
  #define __SMART_ARRAY_H__

#include "macros.h"

using namespace std;

//! Smart array implementation

/*!
A simple implementation for smart arrays. Allocated memory will be deleted automatically
when the smart_array goes out of scope.

Implementation date: 2008

Usage:

\code
smart_array<int> sa(20); // an array of integer holding 20 integers
sa[0] = 17;
\endcode
*/

template <class T>
class smart_array {
private:
  T *array;
  unsigned int item_count;

  //! assignment operator: not allowed
  smart_array &operator=(const smart_array &aa);

  //! copy constructor: not allowed
  smart_array(const smart_array &aa);

public:
  //! sets the internal pointer to null without destructing the array
  /*!
  be careful!
  this is only useful if you want to take back the ownership of the array, which means you want to delete the
  array yourself.
  call operator->() before calling release() and save its return value to a temp variable.
  do not forget to call:
  delete[] temp;
  */
  void release() {
    array = 0;
  } // release

  //! deletes the content of the smart_array and sets it to null
  void clear() {
    delete[] array;
    array = 0;

    item_count = 0;
  }

  //! returns true if the content is not set yet or if it is cleared
  bool is_null() const {
    return (array == 0);
  }

  //! deletes the content of the smart_array and allocates a new array with the given size
  void set_size(unsigned int size) {
    clear();

    item_count = size;
    array = new T[item_count];
  }

  //! returns the size of the array, which is the number of item that can be saved in this array
  unsigned int get_size() const {
    return item_count;
  }

  //! returns the buffer of the array. this buffer will be deleted when the smart_array goes out of scope
  T *get() const {
    return array;
  }

  //! index operator (may throw an exception)
  T &operator[](unsigned int index) {
    INDEX_CHECK(index, item_count);
    return array[index];
  }

  //! index operator (may throw an exception)
  const T &operator[](unsigned int index) const {
    INDEX_CHECK(index, item_count);
    return array[index];
  }

  //! default constructor
  explicit smart_array() : array(0), item_count(0) {
    // nothing to do
  }

  //! constructor
  explicit smart_array(unsigned int item_count) : item_count(item_count) {
    array = new T[item_count];
  }

  //! destructor: deletes the allocated array
  virtual ~smart_array() {
    clear();
  }
};

#endif
